import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
import java.util.*;
import java.util.concurrent.*;

public class MarioGame extends JPanel implements Runnable {

    private Player player;
    private ArrayList<Platform> platforms;
    private ArrayList<Coin> coins;
    private ArrayList<Obstacle> obstacles;  // 遮挡物
    private ArrayList<Enemy> enemies;       // 敌人
    private ExecutorService executor;
    private volatile boolean running;
    private Level level;
    private boolean gameOver = false;
    private boolean movingLeft = false;
    private boolean movingRight = false;

    private int timeRemaining = 300; // 游戏时间限制（秒）
    private Timer gameTimer; // 计时器，用于倒计时

    public MarioGame() {
        player = new Player(100, 100);
        platforms = new ArrayList<>();
        coins = new ArrayList<>();
        obstacles = new ArrayList<>();
        enemies = new ArrayList<>();
        level = new Level();

        executor = Executors.newFixedThreadPool(2);
        running = true;

        // 添加平台
        platforms.add(new Platform(100, 400, 200, 20));
        platforms.add(new Platform(300, 350, 150, 20));
        platforms.add(new Platform(500, 300, 200, 20));
        platforms.add(new Platform(700, 250, 100, 20));
        platforms.add(new Platform(650, 200, 100, 20));
        platforms.add(new Platform(100, 180, 100, 20));
        platforms.add(new Platform(300, 150, 120, 20));


        // 添加金币（更密集分布）
        coins.add(new Coin(150, 370));
        coins.add(new Coin(200, 370));
        coins.add(new Coin(350, 320));
        coins.add(new Coin(400, 320));
        coins.add(new Coin(550, 270));
        coins.add(new Coin(620, 270));
        coins.add(new Coin(700, 220));
        coins.add(new Coin(720, 190));
        coins.add(new Coin(110, 150));
        coins.add(new Coin(320, 120));

        // 添加敌人（速度加快）
        enemies.add(new Enemy(100, 400, 50, 50, 2));
        enemies.add(new Enemy(500, 250, 50, 50, 3));
        enemies.add(new Enemy(200, 300, 50, 50, 2));
        enemies.add(new Enemy(700, 250, 50, 50, -4));

        // 添加遮挡物（不同速度和方向）
        obstacles.add(new Obstacle(200, 300, 50, 50, 2));
        obstacles.add(new Obstacle(600, 200, 50, 50, 3));
        obstacles.add(new Obstacle(500, 200, 50, 50, -3));
        obstacles.add(new Obstacle(700, 150, 50, 50, 4));


        // 设置倒计时
        gameTimer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (timeRemaining > 0 && !gameOver) {
                    timeRemaining--;
                } else if (timeRemaining == 0) {
                    gameOver = true;
                }
            }
        });
        gameTimer.start();
    }

//多线程的利用


    @Override
    public void run() {
        while (running && !gameOver) {
            player.update();

            // 更新左右移动
            if (movingLeft) {
                player.setX(player.getX() - 5);
            }
            if (movingRight) {
                player.setX(player.getX() + 5);
            }

            // 更新敌人
            for (Enemy enemy : enemies) {
                enemy.update();
            }

            for (Platform platform : platforms) {
                platform.update();
            }


            // 更新遮挡物
            for (Obstacle obstacle : obstacles) {
                obstacle.update();
            }

            checkCollisions();
            repaint();

            try {
                Thread.sleep(16); // 约 60 FPS
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        level.renderBackground(g);
        player.render(g);


        for (Platform platform : platforms) {
            platform.render(g);
        }

        for (Coin coin : coins) {
            coin.render(g);
        }

        for (Obstacle obstacle : obstacles) {
            obstacle.render(g);
        }

        for (Enemy enemy : enemies) {
            enemy.render(g);
        }

        // 显示剩余时间
        g.setColor(Color.BLACK);
        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.drawString("Time: " + timeRemaining + "s", 10, 20);

        // 显示分数
        g.drawString("Score: " + player.getScore(), 700, 20);

        // 游戏结束提示
        if (gameOver) {
            g.setColor(Color.BLACK);
            g.setFont(new Font("Arial", Font.BOLD, 50));
            g.drawString("Game Over!", 250, 300);
            g.setFont(new Font("Arial", Font.PLAIN, 30));
            g.drawString("Press R to Restart", 250, 350);
        }
    }

    public void start() {
        Thread gameThread = new Thread(this);
        gameThread.start();

        InputThread inputThread = new InputThread(this);
        executor.submit(inputThread);
    }

    // 处理玩家控制
    public void movePlayer(KeyEvent e) {
        if (gameOver) {
            if (e.getKeyCode() == KeyEvent.VK_R) {
                resetGame();
            }
            return;
        }

        if (e.getKeyCode() == KeyEvent.VK_A) {
            setMovingLeft(true);
        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            setMovingRight(true);
        }
        if (e.getKeyCode() == KeyEvent.VK_W) {
            player.jump();
        }
        if (e.getKeyCode() == KeyEvent.VK_S) {
            player.dropDown(); // 按下 S 键时触发下方块操作
        }
    }

    // 处理按键释放
    public void stopPlayer(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_A) {
            setMovingLeft(false);
        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            setMovingRight(false);
        }
    }

    // 检查碰撞
    private void checkCollisions() {


        for (Platform platform : platforms) {
            if (player.collidesWith(platform)) {
                player.landOnPlatform(platform);
            }
        }

        for (Iterator<Coin> iterator = coins.iterator(); iterator.hasNext();) {
            Coin coin = iterator.next();
            if (player.collidesWith(coin)) {
                player.collectCoin(coin);
                iterator.remove(); // 从列表中移除已收集的金币
            }
        }

        // 如果所有金币被收集，结束游戏
        if (coins.isEmpty()) {
            gameOver = true;
        }

        for (Obstacle obstacle : obstacles) {
            if (player.collidesWith(obstacle)) {
                gameOver = true;
            }
        }

        for (Enemy enemy : enemies) {
            if (player.collidesWith(enemy)) {
                gameOver = true;
            }
        }
    }

    private void resetGame() {
        player = new Player(100, 100);
        platforms = new ArrayList<>();
        coins = new ArrayList<>();
        obstacles = new ArrayList<>();
        enemies = new ArrayList<>();
        level = new Level();

        platforms.add(new Platform(100, 400, 200, 20));
        platforms.add(new Platform(300, 350, 150, 20));
        platforms.add(new Platform(500, 300, 200, 20));
        platforms.add(new Platform(700, 250, 100, 20));
        platforms.add(new Platform(650, 200, 100, 20));
        platforms.add(new Platform(100, 180, 100, 20));
        platforms.add(new Platform(300, 150, 120, 20));


        // 添加金币（更密集分布）
        coins.add(new Coin(150, 370));
        coins.add(new Coin(200, 370));
        coins.add(new Coin(350, 320));
        coins.add(new Coin(400, 320));
        coins.add(new Coin(550, 270));
        coins.add(new Coin(620, 270));
        coins.add(new Coin(700, 220));
        coins.add(new Coin(720, 190));
        coins.add(new Coin(110, 150));
        coins.add(new Coin(320, 120));

        // 添加敌人（速度加快）
        enemies.add(new Enemy(100, 400, 50, 50, 2));
        enemies.add(new Enemy(500, 250, 50, 50, 3));
        enemies.add(new Enemy(200, 300, 50, 50, 2));
        enemies.add(new Enemy(700, 250, 50, 50, -4));

        // 添加遮挡物（不同速度和方向）
        obstacles.add(new Obstacle(200, 300, 50, 50, 2));
        obstacles.add(new Obstacle(600, 200, 50, 50, 3));
        obstacles.add(new Obstacle(500, 200, 50, 50, -3));
        obstacles.add(new Obstacle(700, 150, 50, 50, 4));

        gameOver = false;
        timeRemaining = 300; // 重置时间

        gameTimer.restart(); // 重启计时器

        Thread gameThread = new Thread(this);
        gameThread.start();
    }

    // 设置左右移动标志
    public void setMovingLeft(boolean movingLeft) {
        this.movingLeft = movingLeft;
    }

    public void setMovingRight(boolean movingRight) {
        this.movingRight = movingRight;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Mario Game");
        MarioGame game = new MarioGame();

        frame.setSize(800, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(game);
        frame.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                game.movePlayer(e);
            }

            public void keyReleased(KeyEvent e) {
                game.stopPlayer(e);
            }
        });
        frame.setVisible(true);

        game.start();
    }
}

class Player {
    private int x, y;
    private int velocityY = 0;
    private boolean jumping = false;
    private int score = 0;
    private boolean onGround = false;

    public Player(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void update() {
        if (jumping && onGround) {
            velocityY = -15;
            jumping = false;
            onGround = false;
        }

        y += velocityY;

        if (y < 400) {
            velocityY += 1;
        } else {
            y = 400;
            velocityY = 0;
            onGround = true;
        }
    }

    public void render(Graphics g) {
        g.setColor(Color.RED);
        g.fillRect(x, y, 50, 50);
    }

    public void jump() {
        if (onGround) {
            jumping = true;
        }
    }

    public void landOnPlatform(Platform platform) {
        y = platform.getY() - 50;
        velocityY = 0;
        onGround = true;
    }

    public boolean collidesWith(Platform platform) {
        return (x + 50 > platform.getX() && x < platform.getX() + platform.getWidth() && y + 50 > platform.getY() && y + 50 < platform.getY() + 20);
    }

    public boolean collidesWith(Coin coin) {
        return (x + 50 > coin.getX() && x < coin.getX() + 30 && y + 50 > coin.getY() && y < coin.getY() + 30);
    }

    public boolean collidesWith(Obstacle obstacle) {
        return (x + 50 > obstacle.getX() && x < obstacle.getX() + obstacle.getWidth() && y + 50 > obstacle.getY() && y < obstacle.getY() + obstacle.getHeight());
    }

    public boolean collidesWith(Enemy enemy) {
        return (x + 50 > enemy.getX() && x < enemy.getX() + enemy.getWidth() && y + 50 > enemy.getY() && y < enemy.getY() + enemy.getHeight());
    }

    public void collectCoin(Coin coin) {
        score++;
        System.out.println("Coin collected! Score: " + score);
    }

    public void dropDown() {
        // 简单地模拟掉到平台下方（让角色快速下落）
        if (!onGround) {
            velocityY = 10;  // 增加下落速度
        }
    }

    public int getX() { return x; }
    public void setX(int x) { this.x = x; }
    public int getY() { return y; }
    public void setY(int y) { this.y = y; }
    public int getScore() { return score; }
    public boolean isOnGround() { return onGround; }
}

class Platform {
    private int x, y, width, height;
    private int velocityX = 0;

    public Platform(int x, int y, int width, int height) {
        this(x, y, width, height, 0);
    }

    public Platform(int x, int y, int width, int height, int velocityX) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.velocityX = velocityX;
    }

    public void update() {
        x += velocityX;
        if (x < 0 || x + width > 800) {
            velocityX = -velocityX;
        }
    }

    public void render(Graphics g) {
        g.setColor(Color.BLUE);
        g.fillRect(x, y, width, height);
    }

    public int getX() { return x; }
    public int getY() { return y; }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
}


class Coin {
    private int x, y;

    public Coin(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void render(Graphics g) {
        g.setColor(Color.YELLOW);
        g.fillOval(x, y, 30, 30);
    }

    public int getX() { return x; }
    public int getY() { return y; }
}

class Obstacle {
    private int x, y, width, height, velocityX;

    public Obstacle(int x, int y, int width, int height, int velocityX) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.velocityX = velocityX;
    }

    public void update() {
        x += velocityX;
        if (x < 0 || x > 750) {
            velocityX = -velocityX;
        }
    }

    public void render(Graphics g) {
        g.setColor(Color.DARK_GRAY);
        g.fillRect(x, y, width, height);
    }

    public int getX() { return x; }
    public int getY() { return y; }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
}

class Enemy {
    private int x, y, width, height, velocityX;

    public Enemy(int x, int y, int width, int height, int velocityX) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.velocityX = velocityX;
    }

    public void update() {
        x += velocityX;
        if (x < 0 || x > 750) {
            velocityX = -velocityX;
        }
    }

    public void render(Graphics g) {
        g.setColor(Color.GREEN);
        g.fillRect(x, y, width, height);
    }

    public int getX() { return x; }
    public int getY() { return y; }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
}

class Level {
    private Background background;

    public Level() {
        background = new Background();
    }

    public void renderBackground(Graphics g) {
        background.render(g);
    }
}

class Background {
    public void render(Graphics g) {
        g.setColor(Color.CYAN);
        g.fillRect(0, 0, 800, 600);
        g.setColor(Color.GREEN);
        g.fillRect(0, 450, 800, 200);
    }
}

class InputThread implements Runnable {
    private MarioGame game;

    public InputThread(MarioGame game) {
        this.game = game;
    }

    //多线程的利用
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}